package com.xtool.livewallpaper.video

import android.content.Context
import android.content.Intent
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.opengl.GLSurfaceView
import android.service.wallpaper.WallpaperService
import android.util.Log
import android.view.SurfaceHolder
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.xtool.livewallpaper.WallPaperAliveService
import com.xtool.livewallpaper.WallpaperBootReceiver
import com.xtool.livewallpaper.base.MainApplication
import com.xtool.livewallpaper.base.PrefsHelper
import java.util.prefs.Preferences

class VideoWallpaperService : WallpaperService() {
    companion object {
        var engineInstance: VideoWallpaperEngine? = null
    }

    override fun onCreateEngine(): Engine {
        return VideoWallpaperEngine()
    }

    override fun onDestroy() {
        try {
            engineInstance = null
            PrefsHelper.lastWallpaperType = -1
            WallPaperAliveService.isVideoAlive = false
            super.onDestroy()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    inner class VideoWallpaperEngine : Engine(), Observer<Boolean> {
        private lateinit var glSurfaceView: GLWallpaperSurfaceView
        private lateinit var renderer: GLWallpaperRenderer
        private val videoPath: Uri get() = Uri.parse(PrefsHelper.videoWallpaperPath)
        private var mediaPlayer: SystemMediaPlayer = SystemMediaPlayer()
        private var progress: Int = 0
        private val isMute: Boolean get() = PrefsHelper.isMute
        private var isVisible = false


        private inner class GLWallpaperSurfaceView(context: Context?) : GLSurfaceView(context) {
            override fun getHolder(): SurfaceHolder {
                return surfaceHolder
            }

            fun onDestroy() {
                super.onDetachedFromWindow()
            }
        }

        fun updateWallPaper(isMute: Boolean) {
            progress = 0
            setMute(isMute)
        }

        fun setMute(isMute: Boolean) {
            try {
                PrefsHelper.isMute = isMute
                mediaPlayer.setMute(isMute)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        fun pause() {
            mediaPlayer.pause()
            glSurfaceView.onPause()
        }

        fun play() {
            mediaPlayer.start()
            glSurfaceView.onResume()
        }

        override fun onCreate(surfaceHolder: SurfaceHolder) {
            try {
                super.onCreate(surfaceHolder)
                setTouchEventsEnabled(false)
                PrefsHelper.lastWallpaperType = WallpaperBootReceiver.TYPE_VIDEO
                WallPaperAliveService.isVideoAlive = true
                engineInstance = this
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onDestroy() {
            releasePlayer()
            super.onDestroy()
        }

        override fun onSurfaceCreated(surfaceHolder: SurfaceHolder) {
            try {
                super.onSurfaceCreated(surfaceHolder)
                init()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onVisibilityChanged(visible: Boolean) {
            super.onVisibilityChanged(visible)
            onChanged(visible)
            isVisible = visible
        }

        override fun onSurfaceChanged(
            surfaceHolder: SurfaceHolder, format: Int,
            width: Int, height: Int
        ) {
            try {
                super.onSurfaceChanged(surfaceHolder, format, width, height)
                renderer.setScreenSize(width, height)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onSurfaceDestroyed(holder: SurfaceHolder) {
            try {
                releasePlayer()
                WallPaperAliveService.isVideoAlive = false
                glSurfaceView.onDestroy()
                super.onSurfaceDestroyed(holder)
//                android.os.Process.killProcess(android.os.Process.myPid())
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        private fun createGLSurfaceView() {
            try {
                glSurfaceView = GLWallpaperSurfaceView(this@VideoWallpaperService)
                glSurfaceView.setEGLContextClientVersion(3)
                glSurfaceView.preserveEGLContextOnPause = true
                glSurfaceView.setRenderer(renderer)
                glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }


        private fun init() {
            renderer = GLES30WallpaperRenderer(this@VideoWallpaperService).apply {
                setSourcePlayer(mediaPlayer)
            }
            createGLSurfaceView()
            val width = surfaceHolder.surfaceFrame.width()
            val height = surfaceHolder.surfaceFrame.height()
            renderer.setScreenSize(width, height)
            mediaPlayer.let {
                it.setOnPreparedCallback {
                    onChanged(isVisible)
                }
                it.setMute(isMute)
                it.play(videoPath, progress, false)
            }
            initVideo()
        }

        private fun initVideo() {
            val mmr = MediaMetadataRetriever()
            mmr.setDataSource(MainApplication.gContext, videoPath)
            val rotation = mmr.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION
            )?.toInt() ?: 0
            val width = mmr.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH
            )?.toInt() ?: 0
            val height = mmr.extractMetadata(
                MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT
            )?.toInt() ?: 0
            mmr.release()
            renderer.setVideoSizeAndRotation(width, height, rotation)
        }

        private fun releasePlayer() {
            try {
                progress = 0
                mediaPlayer.stop()
                mediaPlayer.release()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onChanged(value: Boolean) {
            if (value) {
                glSurfaceView.onResume()
                mediaPlayer.start()
            } else {
                mediaPlayer.pause()
                glSurfaceView.onPause()
            }
        }
    }
}